package org.transformatorhuis.unix.server;

import java.io.*;
import java.util.Observer;
import java.util.logging.Logger;

import static org.transformatorhuis.unix.server.THLibrary.THLIB;

/**
 * User: Olivier Van Acker <cyberroadie@transformatorhuis.net>
 * Date: 31-Mar-2010
 */
public class SerializableServer extends AbstractServer {

    Logger logger = Logger.getLogger(SerializableServer.class.getName());
    
    public SerializableServer(String[] args, Serializable processThread) {
        instantiate(args, processThread);
    }

   /**
     * Runs the server
     *
     * @param forks             how many times to JVM needs to be forked
     * @param threadsPerProcess how many threads to be cloned per forked JVM
     * @throws IOException
     */
    @Override
    public void run(int forks, int threadsPerProcess) throws IOException {
        String mode = System.getProperty(MODE_PROPERTY);
        if (forks < 1 || threadsPerProcess < 1) {
            syslog.error("Number of forks and number of threads per process needs to be >0");
            syslog.error("Exiting");
            System.exit(-1);
        }
        if (MODE.equals(mode)) {
            syslog.alert("Starting threads");
                try {
                    File file = serializeObjectToTempFile(processThread);
                    startSerializableThreads(threadsPerProcess, file);
                } catch (RTFMException e) {
                    e.printStackTrace();
                    syslog.error("Threads not implemented correctly, can not clone Threads");
                    System.exit(-1);
                }
        } else {
            syslog.alert("Fork process");
            for (int i = 0; i < forks; i++)
                forkProcess();
        }


    }

     private void startSerializableThreads(int threadsPerProcess, File file) {
        for (int i = 0; i < threadsPerProcess; i++) {
            Object serializedThread;
            try {
                FileInputStream fis = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(fis);
                serializedThread = ois.readObject();
            } catch (IOException e) {
                throw new RTFMException("File with serialized object not found: " + e.toString());
            } catch (ClassNotFoundException e) {
                throw new RTFMException("Error reading object from file: " + e.toString());
            }
            if(serializedThread instanceof Observer)
                thSignalHandler.addObserver((Observer) serializedThread);
            thread((Runnable) serializedThread, true);
        }

        // hang forever
        Object o = new Object();
        synchronized (o) {
            try {
                o.wait();
            } catch (InterruptedException e) {
                System.exit(0);
            }
        }

    }

    private File serializeObjectToTempFile(Object processThread) throws IOException {
        // TODO create temp file, try /var/run/data/ etc.
        File file = new File("server." + THLIB.getpid());
        FileOutputStream fos = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(processThread);
        oos.close();
        fos.close();
        return file;
    }
    
}
